﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;

namespace Behavioral.Tests
{
    [TestFixture]
    public class ArgumentsTests
    {
        #region ArgumentChangesInInitializersShouldBeVisibleToActions

        [Test]
        public void ArgumentChangesInInitializersShouldBeVisibleToActions()
        {
            var testClass = new TestWithMutableInitializer();
            testClass.SetUpMutableInitializer();

            Assert.AreEqual(683, AnActionReadsThatValue.TargetValue);
        }

        class TestWithMutableInitializer : UnitTest<int>
        {
            public void SetUpMutableInitializer()
            {
                GivenThat<AnInitializerMutatesItsArgument>()
                .When<AnActionReadsThatValue>()
                .Then<ItShouldReadTheSameValue>();
            }
        }

        class AnInitializerMutatesItsArgument : IInitializer<int>
        {
            public void SetUp(ref int target)
            {
                target = 683;
            }
        }

        class AnActionReadsThatValue : IAction<int>
        {
            public static int TargetValue;

            public void Execute(int target)
            {
                TargetValue = target;
            }
        }

        class AnActionReadsThatValueAndThrows : IAction<int>
        {
            public static int TargetValue;

            public void Execute(int target)
            {
                TargetValue = target;
                throw new Exception();
            }
        }

        class ItShouldReadTheSameValue : IAssertion<int>
        {
            public void Verify(int target)
            {
                
            }
        }

        #endregion

        #region ArgumentChangesInActionUsedAsInitializerShouldBeVisibleToActions

        [Test]
        public void ArgumentChangesInActionUsedAsInitializerShouldBeVisibleToActions()
        {
            var testClass = new TestWithMutableActionAsInitializer();
            testClass.SetUpMutableActionAsInitializer();

            Assert.AreEqual(683, AnActionReadsThatValue.TargetValue);
        }

        class TestWithMutableActionAsInitializer : UnitTest<int>
        {
            public void SetUpMutableActionAsInitializer()
            {
                GivenThat<AnActionMutatesItsArgument>()
                .When<AnActionReadsThatValue>()
                .Then<ItShouldReadTheSameValue>();
            }
        }

        class AnActionMutatesItsArgument : IActionMutable<int>
        {
            public void Execute(ref int target)
            {
                target = 683;
            }
        }

        #endregion

        #region ArgumentChangesInActionUsedAsInitializerShouldBeVisibleToActionsWhenActionInitializerMismatchesActionProper

        [Test]
        public void ArgumentChangesInActionUsedAsInitializerShouldBeVisibleToActionsWhenActionInitializerMismatchesActionProper()
        {
            var testClass = new TestWithMutableMismatchingActionAsInitializer();
            testClass.SetUpMutableMismatchingActionAsInitializer();

            Assert.AreEqual(683, AnActionReadsThatValue.TargetValue);
        }

        class TestWithMutableMismatchingActionAsInitializer : UnitTest<int, int>
        {
            public void SetUpMutableMismatchingActionAsInitializer()
            {
                GivenThat<AnActionMutatesItsArgument>()
                .When<AnActionReadsThatValue>()
                .Then<ItShouldReadTheSameValueWithReturnValue>();
            }
        }

        class ItShouldReadTheSameValueWithReturnValue : IAssertion<int, int>
        {
            public void Verify(int target, int returnValue)
            {
                
            }
        }

        #endregion

        #region ArgumentChangesInActionUsedAsInitializerShouldBeVisibleToActionsWhenActionInitializerMismatchesActionProperAndExceptionIsExpected

        [Test]
        public void ArgumentChangesInActionUsedAsInitializerShouldBeVisibleToActionsWhenActionInitializerMismatchesActionProperAndExceptionIsExpected()
        {
            var testClass = new TestWithMutableMismatchingActionAsInitializerAndExceptionExpected();
            testClass.SetUpMutableMismatchingActionAsInitializer();

            Assert.AreEqual(683, AnActionReadsThatValue.TargetValue);
        }

        class TestWithMutableMismatchingActionAsInitializerAndExceptionExpected : UnitTest<int, int>
        {
            public void SetUpMutableMismatchingActionAsInitializer()
            {
                GivenThat<AnActionMutatesItsArgument>()
                .When<AnActionReadsThatValueAndThrows>()
                .ThenThrow<Exception>();
            }
        }

        #endregion

    }
}
